]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
browser-plugin: Do not create a new object every time NPPVpluginScriptableNPObject...
authorCarlos Garcia Campos <cgarcia@igalia.com>
Tue, 17 Nov 2015 13:41:03 +0000 (14:41 +0100)
committerMichael Catanzaro <mcatanzaro@gnome.org>
Tue, 17 Nov 2015 19:17:31 +0000 (13:17 -0600)
Merge PluginData and PluginObject structs into a single one and create
the scriptable object associated to the plugin instance in NPP_New. Then,
when NPPVpluginScriptableNPObject is requested we just return the
scriptable object associated to the given instance. This caused the
crashes in NPN_InvokeDefault with WebKit, since we had multiple
scriptable objects for the same instance, but only one of those objects
had the onchange listener installed. Firefox seems to cache the
scriptable object for the instance and therefore NPPVpluginScriptableNPObject
is requested only once.

https://bugzilla.gnome.org/show_bug.cgi?id=737932

browser-plugin/browser-plugin.c

index dbeac336e79c74b1aec381a19092d85fb4f72004..4555a9643ad80765b84c301de7a4f047a0da4d5a 100644 (file)
 
 #define EXTENSION_DISABLE_VERSION_CHECK_KEY "disable-extension-version-validation"
 
-typedef struct {
-  GDBusProxy *proxy;
-} PluginData;
-
 static NPNetscapeFuncs funcs;
 
 static inline gchar *
@@ -145,125 +141,6 @@ check_origin_and_protocol (NPP instance)
   return ret;
 }
 
-/* =============== public entry points =================== */
-
-NPError
-NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
-{
-  /* global initialization routine, called once when plugin
-     is loaded */
-
-  g_debug ("plugin loaded");
-
-  memcpy (&funcs, pfuncs, sizeof (funcs));
-
-  plugin->size = sizeof(NPPluginFuncs);
-  plugin->newp = NPP_New;
-  plugin->destroy = NPP_Destroy;
-  plugin->getvalue = NPP_GetValue;
-  plugin->setwindow = NPP_SetWindow;
-  plugin->event = NPP_HandleEvent;
-
-  return NPERR_NO_ERROR;
-}
-
-NPError
-NP_Shutdown(void)
-{
-  return NPERR_NO_ERROR;
-}
-
-const char*
-NP_GetMIMEDescription(void)
-{
-  return PLUGIN_MIME_STRING;
-}
-
-NPError
-NP_GetValue(void         *instance,
-            NPPVariable   variable,
-            void         *value)
-{
-  switch (variable) {
-  case NPPVpluginNameString:
-    *(char**)value = PLUGIN_NAME;
-    break;
-  case NPPVpluginDescriptionString:
-    *(char**)value = PLUGIN_DESCRIPTION;
-    break;
-  default:
-    ;
-  }
-
-  return NPERR_NO_ERROR;
-}
-
-NPError
-NPP_New(NPMIMEType    mimetype,
-        NPP           instance,
-        uint16_t      mode,
-        int16_t       argc,
-        char        **argn,
-        char        **argv,
-        NPSavedData  *saved)
-{
-  /* instance initialization function */
-  PluginData *data;
-  GError *error = NULL;
-
-  g_debug ("plugin created");
-
-  if (!check_origin_and_protocol (instance))
-    return NPERR_GENERIC_ERROR;
-
-  data = g_slice_new (PluginData);
-  instance->pdata = data;
-
-  /* set windowless mode */
-  funcs.setvalue(instance, NPPVpluginWindowBool, NULL);
-
-  data->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
-                                               G_DBUS_PROXY_FLAGS_NONE,
-                                               NULL, /* interface info */
-                                               "org.gnome.Shell",
-                                               "/org/gnome/Shell",
-                                               "org.gnome.Shell.Extensions",
-                                               NULL, /* GCancellable */
-                                               &error);
-  if (!data->proxy)
-    {
-      /* ignore error if the shell is not running, otherwise warn */
-      if (error->domain != G_DBUS_ERROR ||
-          error->code != G_DBUS_ERROR_NAME_HAS_NO_OWNER)
-        {
-          g_warning ("Failed to set up Shell proxy: %s", error->message);
-        }
-      g_clear_error (&error);
-      return NPERR_GENERIC_ERROR;
-    }
-
-  g_debug ("plugin created successfully");
-
-  return NPERR_NO_ERROR;
-}
-
-NPError
-NPP_Destroy(NPP           instance,
-           NPSavedData **saved)
-{
-  /* instance finalization function */
-
-  PluginData *data = instance->pdata;
-
-  g_debug ("plugin destroyed");
-
-  g_object_unref (data->proxy);
-
-  g_slice_free (PluginData, data);
-
-  return NPERR_NO_ERROR;
-}
-
 /* =================== scripting interface =================== */
 
 typedef struct {
@@ -334,45 +211,18 @@ static NPObject *
 plugin_object_allocate (NPP      instance,
                         NPClass *klass)
 {
-  PluginData *data = instance->pdata;
-  PluginObject *obj = g_slice_new0 (PluginObject);
+  PluginObject *obj = (PluginObject *) funcs.memalloc (sizeof (PluginObject));
 
+  memset (obj, 0, sizeof (PluginObject));
   obj->instance = instance;
-  obj->proxy = g_object_ref (data->proxy);
-  obj->settings = g_settings_new (SHELL_SCHEMA);
-  obj->signal_id = g_signal_connect (obj->proxy, "g-signal",
-                                     G_CALLBACK (on_shell_signal), obj);
 
-  obj->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
-                                         "org.gnome.Shell",
-                                         G_BUS_NAME_WATCHER_FLAGS_NONE,
-                                         on_shell_appeared,
-                                         NULL,
-                                         obj,
-                                         NULL);
-
-  g_debug ("plugin object created");
-
-  return (NPObject*)obj;
+  return (NPObject*) obj;
 }
 
 static void
 plugin_object_deallocate (NPObject *npobj)
 {
-  PluginObject *obj = (PluginObject*)npobj;
-
-  g_signal_handler_disconnect (obj->proxy, obj->signal_id);
-  g_object_unref (obj->proxy);
-
-  if (obj->listener)
-    funcs.releaseobject (obj->listener);
-
-  if (obj->watch_name_id)
-    g_bus_unwatch_name (obj->watch_name_id);
-
-  g_debug ("plugin object destroyed");
-
-  g_slice_free (PluginObject, obj);
+  funcs.memfree (npobj);
 }
 
 static inline gboolean
@@ -1023,6 +873,149 @@ init_methods_and_properties (void)
   onextension_changed_id = funcs.getstringidentifier ("onchange");
 }
 
+/* =============== public entry points =================== */
+
+NPError
+NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
+{
+  /* global initialization routine, called once when plugin
+     is loaded */
+
+  g_debug ("plugin loaded");
+
+  memcpy (&funcs, pfuncs, sizeof (funcs));
+
+  plugin->size = sizeof(NPPluginFuncs);
+  plugin->newp = NPP_New;
+  plugin->destroy = NPP_Destroy;
+  plugin->getvalue = NPP_GetValue;
+  plugin->setwindow = NPP_SetWindow;
+  plugin->event = NPP_HandleEvent;
+
+  return NPERR_NO_ERROR;
+}
+
+NPError
+NP_Shutdown(void)
+{
+  return NPERR_NO_ERROR;
+}
+
+const char*
+NP_GetMIMEDescription(void)
+{
+  return PLUGIN_MIME_STRING;
+}
+
+NPError
+NP_GetValue(void         *instance,
+            NPPVariable   variable,
+            void         *value)
+{
+  switch (variable) {
+  case NPPVpluginNameString:
+    *(char**)value = PLUGIN_NAME;
+    break;
+  case NPPVpluginDescriptionString:
+    *(char**)value = PLUGIN_DESCRIPTION;
+    break;
+  default:
+    ;
+  }
+
+  return NPERR_NO_ERROR;
+}
+
+NPError
+NPP_New(NPMIMEType    mimetype,
+        NPP           instance,
+        uint16_t      mode,
+        int16_t       argc,
+        char        **argn,
+        char        **argv,
+        NPSavedData  *saved)
+{
+  /* instance initialization function */
+  PluginObject *obj;
+  GError *error = NULL;
+
+  g_debug ("plugin created");
+
+  if (!check_origin_and_protocol (instance))
+    return NPERR_GENERIC_ERROR;
+
+  /* set windowless mode */
+  funcs.setvalue(instance, NPPVpluginWindowBool, NULL);
+
+  g_debug ("creating scriptable object");
+  init_methods_and_properties ();
+  obj = (PluginObject *) funcs.createobject (instance, &plugin_class);
+  instance->pdata = obj;
+
+  obj->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                              G_DBUS_PROXY_FLAGS_NONE,
+                                              NULL, /* interface info */
+                                              "org.gnome.Shell",
+                                              "/org/gnome/Shell",
+                                              "org.gnome.Shell.Extensions",
+                                              NULL, /* GCancellable */
+                                              &error);
+  if (!obj->proxy)
+    {
+      /* ignore error if the shell is not running, otherwise warn */
+      if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER))
+        {
+          g_warning ("Failed to set up Shell proxy: %s", error->message);
+        }
+      g_clear_error (&error);
+      return NPERR_GENERIC_ERROR;
+    }
+
+  obj->settings = g_settings_new (SHELL_SCHEMA);
+  obj->signal_id = g_signal_connect (obj->proxy, "g-signal",
+                                     G_CALLBACK (on_shell_signal), obj);
+  obj->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                         "org.gnome.Shell",
+                                         G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                         on_shell_appeared,
+                                         NULL,
+                                         obj,
+                                         NULL);
+
+  g_debug ("plugin created successfully");
+
+  return NPERR_NO_ERROR;
+}
+
+NPError
+NPP_Destroy(NPP           instance,
+           NPSavedData **saved)
+{
+  /* instance finalization function */
+  PluginObject *obj = (PluginObject *) instance->pdata;
+
+  if (!obj)
+    return NPERR_INVALID_INSTANCE_ERROR;
+
+  g_debug ("plugin destroyed");
+
+  g_signal_handler_disconnect (obj->proxy, obj->signal_id);
+  g_object_unref (obj->proxy);
+
+  if (obj->listener)
+    funcs.releaseobject (obj->listener);
+
+  if (obj->restart_listener)
+    funcs.releaseobject (obj->restart_listener);
+
+  if (obj->watch_name_id)
+    g_bus_unwatch_name (obj->watch_name_id);
+
+  funcs.releaseobject((NPObject *)obj);
+
+  return NPERR_NO_ERROR;
+}
+
 NPError
 NPP_GetValue(NPP          instance,
             NPPVariable  variable,
@@ -1033,9 +1026,10 @@ NPP_GetValue(NPP          instance,
   switch (variable) {
   case NPPVpluginScriptableNPObject:
     g_debug ("creating scriptable object");
-    init_methods_and_properties ();
+    if (!instance->pdata)
+      return NPERR_INVALID_INSTANCE_ERROR;
 
-    *(NPObject**)value = funcs.createobject (instance, &plugin_class);
+    *(NPObject**)value = instance->pdata;
     break;
 
   default: